﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using TEL.ClientClasses;
using TEL.ClientClasses.Private;
using TEL.ClientClasses.SipInterfaces;

namespace TEL.TelPhoneF.Controls
{
    public partial class LineManager : CustomPanel, ILineManager
    {
        private object mLock = new object();
        private List<ButtonLine> btns = new List<ButtonLine>();
        public LineManager()
        {
            InitializeComponent();
        }

        public void SetLineState(string lineCall, CallState state)
        {
            lock (mLock)
            {
                try
                {
                    this.Invoke(new MethodInvoker(delegate()
                                                      {
                                                          try
                                                          {
                                                              ButtonLine b =
                                                                  (from q in btns
                                                                   where q.LineCall == lineCall
                                                                   select q).First();
                                                              b.State = state;
                                                          }
                                                          catch (Exception)
                                                          {

                                                          }
                                                      }), null);
                }
                catch (Exception)
                {
                }
            }
        }

        public void ToHoldAll(CallState state)
        {
            try
            {
                List<ButtonLine> active =
                    (from q in btns where q.Enabled && q.State == state select q).
                        ToList();
                active.ForEach(b => b.LinePhone.ToggleCallOnHold());
            }
            catch (Exception)
            {
            }
        }

        public bool HasLine(string lineCall)
        {
            bool res = false;
            lock (btns)
            {
                res = (from q in btns
                       where q.LineCall == lineCall
                       select q).Count() > 0;
            }
            return res;
        }

        public string GetLineIsWait(bool isOutCall)
        {
            string res = string.Empty;
            lock (btns)
            {
                try
                {
                    ButtonLine l = (from q in btns
                                    where q.State == CallState.WaitingToAccept && q.IsOutCall == isOutCall
                                    select q).Last();

                    res = l.LineCall;
                }
                catch (Exception)
                {
                }
            }
            return res;
        }

        public int GetLineNumberIsDialTone()
        {
            int res = 0;
            lock (btns)
            {
                try
                {
                    ButtonLine l = (from q in btns
                                    where q.State == CallState.DialTone
                                    select q).First();

                    res = l.LineNumber;
                }
                catch
                {
                }
            }
            return res;
        }

        private delegate void DCreateLineButons(List<SipLine> lines);

        private void CreateLineButtons(List<SipLine> lines)
        {

            lines.Sort(new Comparison<SipLine>((a, b) => b.LineNumber.CompareTo(a.LineNumber)));
            this.Controls.Clear();
            btns.Clear();
            foreach (SipLine sipLine in lines)
            {
                ButtonLine btnLine = new ButtonLine();
                btnLine.LineCall = null;
                btnLine.Dock = System.Windows.Forms.DockStyle.Left;
                btnLine.AllowDrop = true;
                btnLine.LinePhone = sipLine;
                btnLine.ImageAlign = System.Drawing.ContentAlignment.BottomRight;
                btnLine.State = CallState.Entity;
                btnLine.TextAlign = System.Drawing.ContentAlignment.TopLeft;
                btnLine.Name = "button" + sipLine.LineNumber.ToString();
                btnLine.LineNumber = sipLine.LineNumber;
                btnLine.Size = new System.Drawing.Size(30, 25);
                btnLine.Text = sipLine.LineNumber.ToString();
                btnLine.UseVisualStyleBackColor = true;
                
                btnLine.KeyDown += KeyDownEvent;
                btnLine.Click += new System.EventHandler(this.Line_Click);

                this.Controls.Add(btnLine);
                btns.Add(btnLine);
            }
            btns.Sort(new Comparison<ButtonLine>((a, b) => a.LineNumber.CompareTo(b.LineNumber)));
        }

        public void CreateSipLines(List<SipLine> lines)
        {
            try
            {
                this.Invoke(new DCreateLineButons(CreateLineButtons), lines);
            }
            catch (Exception)
            {
            }
        }

        public string SearhLineCall(CallState state)
        {
            string res = string.Empty;
            lock (btns)
            {
                try
                {
                    if (state == CallState.Entity)
                    {
                        var l = from q in btns
                                where
                                    (q.State != CallState.Entity && !string.IsNullOrEmpty(q.LineCall))
                                select q;
                        res = l.Last().LineCall;
                    }
                    else
                    {
                        var l = from q in btns
                                select q;
                        res = l.Last().LineCall;
                    }
                }
                catch (Exception)
                {
                }
            }
            return res;
        }

        public CallState GetLineStateByLineCall(string lineCall)
        {
            ButtonLine b = null;
            lock (btns)
            {
                try
                {
                    b =
                        (from q in btns
                         where q.LineCall == lineCall
                         select q).First();
                }
                catch (Exception)
                {
                }
            }
            return b != null ? b.State : CallState.Entity;
        }

        public event EventHandler<SipLineEventArgs> ActiveLineChange;
        public event EventHandler<SipLineEventArgs> TransferLineChange;

        private SipLine m_activeLine;
        public SipLine ActiveLine
        {
            get
            {
                if (m_activeLine == null || m_activeLine.State==CallState.Entity) return null;
                return m_activeLine;
            }
            set
            {
                //if (value == null)
                //{}
                //if (m_activeLine == null || !m_activeLine.Equals(value))
                {
                    m_activeLine = value;
                    if (ActiveLineChange != null) ActiveLineChange(this, new SipLineEventArgs(m_activeLine));
                }
            }
        }

        private SipLine m_transferLine;
        public SipLine TransferLine
        {
            get { return m_transferLine; }
            set
            {
                if (value != null)
                {
                    m_transferLine = value;
                    m_transferLine.CallChanged += new EventHandler<CallEventArgs>(m_transferLine_CallChanged);
                    m_transferLine.ToggleCallOnHold();
                }
                else
                {
                    m_transferLine = value;
                }
                if (TransferLineChange != null)TransferLineChange(this, new SipLineEventArgs(m_transferLine));
            }
        }

        void m_transferLine_CallChanged(object sender, CallEventArgs e)
        {
            if (e.Caller == null) TransferLine = null;
        }

        public event EventHandler<SipLineEventArgs> XferLineChange;


        private SipLine m_xferLine;
        public SipLine XferLine
        {
            get { return m_xferLine; }
            set
            {
                if (value != null)
                {
                    m_xferLine = value;
                    m_xferLine.CallChanged += new EventHandler<CallEventArgs>(m_xferLine_CallChanged);
                    m_xferLine.ToggleCallOnHold();
                }
                else
                {
                    m_xferLine = value;
                }
                if (XferLineChange != null) XferLineChange(this, new SipLineEventArgs(m_xferLine));
            }
        }

        void m_xferLine_CallChanged(object sender, CallEventArgs e)
        {
            if(e.Caller == null) XferLine = null;
        }

       private void Line_Click(object sender, EventArgs e)
        {
            try
            {
                ButtonLine btn = sender as ButtonLine;
                if (btn == null) throw new ArgumentNullException("Нет кнопки");
                if (btn.LinePhone == null) throw new ArgumentNullException("Нет линии в кнопке");
                if (btn.State ==CallState.WaitingToAccept)
                {
                    btn.LinePhone.State = CallState.Active;
                    btn.LinePhone.CallTerminated();
                    return;
                }
                ActiveLine = btn.LinePhone;

            }
            catch (Exception)
            {

            }
        }

        private void KeyLine(int key)
        {
            ButtonLine b = null;
            try
            {
                b = (from q in btns where q.LineNumber == key select q).First();
                if(b!= null) b.PerformClick();
            }
            catch (Exception)
            {
                
            }
        }

        public bool BtnPanel_KeyDown(KeyEventArgs e)
        {
            bool res = false;
            if (e.Alt )
            switch (e.KeyCode)
            {
                case Keys.D0: KeyLine(0); res = true;
                    break;
                case Keys.D1: KeyLine(1); res = true;
                    break;
                case Keys.D2: KeyLine(2); res = true;
                    break;
                case Keys.D3: KeyLine(3); res = true;
                    break;
                case Keys.D4: KeyLine(4); res = true;
                    break;
                case Keys.D5: KeyLine(5); res = true;
                    break;
                case Keys.D6: KeyLine(6); res = true;
                    break;
                case Keys.D7: KeyLine(7); res = true;
                    break;
                case Keys.D8: KeyLine(8); res = true;
                    break;
                case Keys.D9: KeyLine(9); res = true;
                    break;

                case Keys.NumPad0: KeyLine(0); res = true;
                    break;
                case Keys.NumPad1: KeyLine(1); res = true;
                    break;
                case Keys.NumPad2: KeyLine(2); res = true;
                    break;
                case Keys.NumPad3: KeyLine(3); res = true;
                    break;
                case Keys.NumPad4: KeyLine(4); res = true;
                    break;
                case Keys.NumPad5: KeyLine(5); res = true;
                    break;
                case Keys.NumPad6: KeyLine(6); res = true;
                    break;
                case Keys.NumPad7: KeyLine(7); res = true;
                    break;
                case Keys.NumPad8: KeyLine(8); res = true;
                    break;
                case Keys.NumPad9: KeyLine(9); res = true;
                    break;
            }
            return res;
        }
    }
}
